
package com.monlyu.util;

import java.io.File;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
import java.util.UUID;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import org.apache.commons.io.FileUtils;

/**
 * 一些安全的的操作
 * 
 * @author monlyu
 */
public class SecurityUtil {

    /* -=-=-=-=-=-=-=-=-=-=-=-Md5加解密=--=-=-=-=-=-=-=-=-=-=-=-=-==-=-= */
    /**
     * 获取字符串的Md5值
     * 
     * @param input
     *            字符串
     * @return Md5值
     */
    public static String md5(String input){
        return md5(input.getBytes());
    }

    /**
     * 获取字符串的Md5值
     * 
     * @param source
     *            字符数组
     * @return Md5值
     */
    public static String md5(byte[] source){
        String result = null;
        final char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(source);
            byte tmp[] = md.digest();
            char str[] = new char[16 * 2];
            int k = 0;
            for (int i = 0; i < 16; i++) {
                byte b = tmp[i];
                str[k++] = hexDigits[b >>> 4 & 0xf];
                str[k++] = hexDigits[b & 0xf];
            }
            result = new String(str);
        }
        catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 文件的Md5值
     * 
     * @param file
     *            需求Md5值的文件
     * @return Md5加密后的字串
     */
    public static String md5(File file){
        String md5str = null;
        try {
            md5str = md5(FileUtils.readFileToByteArray(file));
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        return md5str;
    }

    /**
     * =-=-=-=-=-=-=-=-=-=-=-=DES 加解密-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
     */
    private static final String CRYPT_KEY = "@4Rde%D_e*RDF";
    private final static String DES = "DES";

    /**
     * 加密
     */

    private static byte[] encrypt(byte[] src, byte[] key) throws Exception{
        SecureRandom sr = new SecureRandom();// DES算法要求有一个可信任的随机数源
        DESKeySpec dks = new DESKeySpec(key);// 从原始密匙数据创建DESKeySpec对象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);// 创建一个密匙工厂，然后用它把DESKeySpec转换成,一个SecretKey对象
        SecretKey securekey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance(DES);// Cipher对象实际完成加密操作
        cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);// 用密匙初始化Cipher对象
        return cipher.doFinal(src);
    }

    /**
     * 解密
     */

    private static byte[] decrypt(byte[] src, byte[] key) throws Exception{
        SecureRandom sr = new SecureRandom();// DES算法要求有一个可信任的随机数源
        DESKeySpec dks = new DESKeySpec(key); // 从原始密匙数据创建一个DESKeySpec对象
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);// 创建一个密匙工厂，然后用它把DESKeySpec对象转换成,一个SecretKey对象
        SecretKey securekey = keyFactory.generateSecret(dks);
        Cipher cipher = Cipher.getInstance(DES);// Cipher对象实际完成解密操作
        cipher.init(Cipher.DECRYPT_MODE, securekey, sr);// 用密匙初始化Cipher对象
        return cipher.doFinal(src);
    }

    /**
     * 用默认密码解密
     */

    public final static String desDecode(String data){
        String reval = "";
        try {
            reval = new String(decrypt(ByteUtil.hex2byte(data.getBytes()), CRYPT_KEY.getBytes()));
        }
        catch (Exception e) {
            LogUtil.log(SecurityUtil.class, e).warn("DES解密失败");
        }
        return reval;
    }

    /** 用自己的密码加密 */
    public final static String desDecode(String data, String key){
        byte[] byts = null;
        byte[] keys = null;
        try {
            if (StringUtil.isEmpty(key)) {
                keys = CRYPT_KEY.getBytes();
            } else {
                keys = ByteUtil.strTo8byte(key);
            }
            byts = decrypt(ByteUtil.hex2byte(data.getBytes()), keys);
        }
        catch (Exception e) {
            LogUtil.log(SecurityUtil.class, e).warn("DES解密失败");
        }
        return new String(byts);
    }

    /**
     * 默认密码加密
     */

    public final static String desEncode(String password){
        String value = null;
        try {
            value = ByteUtil.byte2hex(encrypt(password.getBytes(), CRYPT_KEY.getBytes()));
        }
        catch (Exception e) {
            LogUtil.log(SecurityUtil.class, e).warn("DES加密失败");
        }
        return value;
    }

    /** 用自己的密钥进行加密 */
    public final static String desEncode(String password, String key){
        String value = "";
        byte[] tmp = null;
        try {
            if (StringUtil.isEmpty(key)) {
                tmp = CRYPT_KEY.getBytes();
            } else {
                tmp = ByteUtil.strTo8byte(key);
            }
            value = ByteUtil.byte2hex(encrypt(password.getBytes(), tmp));
        }
        catch (Exception e) {
            LogUtil.log(SecurityUtil.class, e).warn("DES加密失败");
        }
        return value;
    }

    /**
     * 回去随机的UUID文件.用于上传文件的文件名
     * 
     * @author monlyu
     * @since 2010-1-30
     */
    public static UUID getUUID(){
        return UUID.randomUUID();
    }

    /**
     * 获取UUID类的字符串
     * 
     * @author monlyu
     * @since 2010-1-30
     */
    public static String getUUIDStr(){
        return getUUID().toString();
    }

    public static void main(String[] args){
        System.out.println(md5("sa"));
    }

    public static String encode(String date, int... size){
        int length = size.length == 0 ? 100 : size[0];
        StringBuilder allS = new StringBuilder("*");
        for (int i = 0; i < date.length(); i++) {
            allS.append(getCharStr(length));
            allS.append(date.charAt(i));
        }
        return allS.toString();
    }

    public static String decode(String s, int... size){
        int length = size.length == 0 ? 100 : size[0];
        int mod = s.length() / length;
        StringBuilder re = new StringBuilder();
        for (int i = 1; i <= mod; i++) {
            re.append(s.charAt(i * length + i));
        }
        return re.toString();
    }

    private static String getCharStr(int leng){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < leng; i++) {
            sb.append((char) nextInt(33, 126));
        }
        return sb.toString();
    }

    private static int nextInt(int begin, int end){
        int get = new Random().nextInt(end);
        if (get < begin) {
            return nextInt(begin, end);
        } else {
            return get;
        }
    }
}